<html>
  <head>
    <meta charset="UTF-8">
    <style type="text/css">
    div.histo {
        visibility: hidden
    }
    </style>
    <!--Load the AJAX API-->
    <script type="text/javascript" src="https://www.google.com/jsapi"></script>
    <script type="text/javascript">
    (function() {
      var out$ = typeof exports != 'undefined' && exports || this;

      var doctype = '<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">';

      function inlineImages(callback) {
        var images = document.querySelectorAll('svg image');
        var left = images.length;
        if (left == 0) {
          callback();
        }
        for (var i = 0; i < images.length; i++) {
          (function(image) {
            if (image.getAttribute('xlink:href')) {
              var href = image.getAttribute('xlink:href').value;
              if (/^http/.test(href) && !(new RegExp('^' + window.location.host).test(href))) {
                throw new Error("Cannot render embedded images linking to external hosts.");
              }
            }
            var canvas = document.createElement('canvas');
            var ctx = canvas.getContext('2d');
            var img = new Image();
            img.src = image.getAttribute('xlink:href');
            img.onload = function() {
              canvas.width = img.width;
              canvas.height = img.height;
              ctx.drawImage(img, 0, 0);
              image.setAttribute('xlink:href', canvas.toDataURL('image/png'));
              left--;
              if (left == 0) {
                callback();
              }
            }
          })(images[i]);
        }
      }

      function styles(dom) {
        var css = "";
        var sheets = document.styleSheets;
        for (var i = 0; i < sheets.length; i++) {
          var rules = sheets[i].cssRules;
          if (rules != null) {
            for (var j = 0; j < rules.length; j++) {
              var rule = rules[j];
              if (typeof(rule.style) != "undefined") {
                css += rule.selectorText + " { " + rule.style.cssText + " }\n";
              }
            }
          }
        }

        var s = document.createElement('style');
        s.setAttribute('type', 'text/css');
        s.innerHTML = "<![CDATA[\n" + css + "\n]]>";

        var defs = document.createElement('defs');
        defs.appendChild(s);
        return defs;
      }

      out$.svgAsDataUri = function(el, scaleFactor, cb) {
        scaleFactor = scaleFactor || 1;

        inlineImages(function() {
          var outer = document.createElement("div");
          var clone = el.cloneNode(true);
          var width = parseInt(
            clone.getAttribute('width')
              || clone.style.width
              || out$.getComputedStyle(el).getPropertyValue('width')
          );
          var height = parseInt(
            clone.getAttribute('height')
              || clone.style.height
              || out$.getComputedStyle(el).getPropertyValue('height')
          );

          var xmlns = "http://www.w3.org/2000/xmlns/";

          clone.setAttribute("version", "1.1");
          clone.setAttributeNS(xmlns, "xmlns", "http://www.w3.org/2000/svg");
          clone.setAttributeNS(xmlns, "xmlns:xlink", "http://www.w3.org/1999/xlink");
          clone.setAttribute("width", width * scaleFactor);
          clone.setAttribute("height", height * scaleFactor);
          clone.setAttribute("viewBox", "0 0 " + width + " " + height);
          outer.appendChild(clone);

          clone.insertBefore(styles(clone), clone.firstChild);

          var svg = doctype + outer.innerHTML;
          var uri = 'data:image/svg+xml;base64,' + window.btoa(unescape(encodeURIComponent(svg)));
          if (cb) {
            cb(uri);
          }
        });
      }

      out$.saveSvgAsPng = function(el, name, scaleFactor) {
        out$.svgAsDataUri(el, scaleFactor, function(uri) {
          var image = new Image();
          image.src = uri;
          image.onload = function() {
            var canvas = document.createElement('canvas');
            canvas.width = image.width;
            canvas.height = image.height;
            var context = canvas.getContext('2d');
            context.drawImage(image, 0, 0);

            var a = document.createElement('a');
            a.download = name;
            a.href = canvas.toDataURL('image/png');
            document.body.appendChild(a);
            a.click();
          }
        });
      }
    })();
    </script>
    <script type="text/javascript">

      if (window.File && window.FileReader && window.FileList && window.Blob) {
        // Great success! All the File APIs are supported.
      } else {
        alert('The File APIs are not fully supported in this browser.');
      }

      // Load the Visualization API and the corechart package.
      google.load('visualization', '1.0', {'packages':['corechart']});

      // Global data series
      var dataSeries_g = [];

      function drawChart() {

        if (dataSeries_g.length == 0) {
          return;
        }

        var data = google.visualization.arrayToDataTable(dataSeries_g);

        var ticks =
          [{v:1,f:'0%'},
           {v:10,f:'90%'},
           {v:100,f:'99%'},
           {v:1000,f:'99.9%'},
           {v:10000,f:'99.99%'},
           {v:100000,f:'99.999%'},
           {v:1000000,f:'99.9999%'}];

        var options = {
          title: 'Histogram',
          width: 800,
          height: 480,
          hAxis: {title: 'Percentile', minValue: 0, logScale: true, ticks:ticks },
          vAxis: {title: 'Latency (µs)', minValue: 0 },
          legend: {position: 'bottom'}
        };

        var chart = new google.visualization.LineChart(document.getElementById('chart_div'));

        // add tooltips with correct percentile text to data:
        var columns = [0];
        for (var i = 1; i < data.getNumberOfColumns(); i++) {
          columns.push(i);
          columns.push({
            type: 'string',
            properties: {
                role: 'tooltip'
            },
            calc: (function (j) {
                return function (dt, row) {
              var percentile = 100.0 - (100.0/dt.getValue(row, 0));
              return dt.getColumnLabel(j) + ': ' + 
                percentile.toPrecision(6) +
                 '\%\'ile = ' + dt.getValue(row, j) + ' usec'
                }
            })(i)
          });
        }
        var view = new google.visualization.DataView(data);
        view.setColumns(columns);

        chart.draw(view, options);
      }
    </script>
    <script type="text/javascript">
        function appendDataSeries(histo, name, dataSeries) {
          var series;
          var seriesCount;
          if (dataSeries.length == 0) {
            series = [ ['X', name] ];
            seriesCount = 1;
          } else {
            series = dataSeries;
            series[0].push(name);
            seriesCount = series[0].length - 1;
          }

          var lines = histo.split("\n");

          var seriesIndex = 1;
          for (var i = 0; i < lines.length; i++) {
            var line = lines[i].trim();
            var values = line.trim().split(/[ ]+/);

            if (line[0] != '#' && values.length == 4) {

              var y = parseFloat(values[0]);
              var x = parseFloat(values[3]);

              if (!isNaN(x) && !isNaN(y)) {

                if (seriesIndex >= series.length) {
                  series.push([x]);
                }

                while (series[seriesIndex].length < seriesCount) {
                  series[seriesIndex].push(null);
                }

                series[seriesIndex].push(y);
                seriesIndex++;
              }
            }
          }

          while (seriesIndex < series.length) {
            series[seriesIndex].push(null);
            seriesIndex++;
          }

          return series;
        }

        function loadFile(event) {
          var files = event.target.files;

          for (var i = 0, f; f = files[i]; i++) {
            var reader = new FileReader();
            reader.onload = (function(theFile) {
              return function(e) {
                var data = e.target.result;
                dataSeries_g = appendDataSeries(data, theFile.name, dataSeries_g);
                drawChart();
              };
            })(f);

            reader.readAsText(f);            
          }
          return {typed: ''};
        }

        function doExport(event) {
          saveSvgAsPng(document.querySelector('svg'), 'Histogram');
          return {typed: ''};
        }
    </script>
  </head>

  <body>
    <!--Div that will hold the chart-->
    <div id="chart_div">Please select a histogram file</div>
    <input type='file' onchange='loadFile(event)' multiple>
    <button type='button' onclick='doExport(event)'>Export Image</button>
  </body>
</html>
